package com.cn.psys.system.controller;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.serializer.BigDecimalCodec;
import com.cn.psys.tools.excel.ExcelUtil;
import org.apache.commons.collections.map.LinkedMap;
import org.apache.shiro.crypto.hash.Hash;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import com.cn.psys.system.service.IJhfbStuService;
import com.cn.psys.system.entity.JhfbStu;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.*;

import com.cn.psys.base.BaseResponse;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import com.cn.psys.mybatisplus.MybatisPlusQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import cn.hutool.core.util.IdUtil;

import javax.servlet.http.HttpServletResponse;

/**
 * <p>
 * 前端控制器
 * </p>
 *
 * @author zhuwei
 * @since 2020-08-18
 */
@RestController
@RequestMapping("/jhfb-stu")
public class JhfbStuController {
    private IJhfbStuService targetService;

    @Autowired
    public JhfbStuController(IJhfbStuService targetService) {
        this.targetService = targetService;
    }


    /**
     * showdoc
     *
     * @param page 非必选 string 页数（不传默认第一页）
     * @param rows 非必选 string 行数（不传默认一页10行）
     * @catalog JhfbStu
     * @title 分页列表
     * @description 分页列表接口
     * @method post
     * @url http://localhost/user/sys-user/list
     * @remark 无
     * @number 1
     */
    @RequiresPermissions("JhfbStu:list")
    @RequestMapping("/list")
    @ResponseBody
    public BaseResponse findListByPage(@RequestParam(required = false) String paramData, @RequestParam(name = "page", defaultValue = "1") int pageIndex, @RequestParam(name = "rows", defaultValue = "10") int step) {
        QueryWrapper<JhfbStu> queryWrapper = MybatisPlusQuery.parseWhereSql(paramData);
        Page page = new Page(pageIndex, step);
        return BaseResponse.success(targetService.page(page, queryWrapper));
    }


    /**
     * showdoc
     *
     * @param 无 无 无 无
     * @catalog JhfbStu
     * @title 所有数据列表
     * @description 所有数据列表
     * @method post
     * @url http://localhost/user/sys-user/all
     * @remark 无
     * @number 2
     */
    @RequiresPermissions("JhfbStu:all")
    @RequestMapping("/all")
    @ResponseBody
    public BaseResponse findAll(@RequestParam(required = false) String paramData) {
        QueryWrapper<JhfbStu> queryWrapper = MybatisPlusQuery.parseWhereSql(paramData);
        return BaseResponse.success(targetService.list(queryWrapper));
    }


    /**
     * showdoc
     *
     * @param id 必选 Long 页数
     * @catalog JhfbStu
     * @title 详情页面
     * @description 详情页面接口
     * @method post
     * @url http://localhost/user/sys-user/find
     * @remark 无
     * @number 3
     */
    @RequiresPermissions("JhfbStu:find")
    @RequestMapping("/find")
    @ResponseBody
    public BaseResponse find(@RequestParam(required = false) String paramData) {
        QueryWrapper<JhfbStu> queryWrapper = MybatisPlusQuery.parseWhereSql(paramData);
        JhfbStu JhfbStu = null;
        try {
            JhfbStu = targetService.getOne(queryWrapper, true);
        } catch (Exception e) {
            e.printStackTrace();
        }
        if (JhfbStu == null) {
            return BaseResponse.error("无查询结果");
        }
        return BaseResponse.success(JhfbStu);
    }

    /**
     * showdoc
     *
     * @param JhfbStu 必选 JhfbStu 保存对象
     * @catalog JhfbStu
     * @title 新增数据
     * @description 新增数据接口
     * @method post
     * @url http://localhost/user/sys-user/add
     * @remark 无
     * @number 4
     */
    @RequiresPermissions("JhfbStu:add")
    @RequestMapping(value = "/add", method = RequestMethod.POST)
    @ResponseBody
    public BaseResponse addItem(@RequestBody JhfbStu JhfbStu) {
        String uuid = IdUtil.randomUUID();
        JhfbStu.setUuid(uuid);
        boolean isOk = targetService.save(JhfbStu);
        if (isOk) {
            return BaseResponse.success(uuid);
        }
        return BaseResponse.error("数据添加失败");
    }


    /**
     * showdoc
     *
     * @param JhfbStu 必选 JhfbStu 保存对象
     * @catalog JhfbStu
     * @title 更新数据
     * @description 更新数据接口
     * @method post
     * @url http://localhost/user/sys-user/add
     * @remark 无
     * @number 5
     */
    @RequiresPermissions("JhfbStu:update")
    @RequestMapping(value = "/update", method = RequestMethod.POST)
    @ResponseBody
    public BaseResponse updateItem(@RequestBody JhfbStu JhfbStu) {
        boolean isOk = targetService.updateById(JhfbStu);
        if (isOk) {
            return BaseResponse.success("数据更改成功！");
        }
        return BaseResponse.error("数据更改失败");
    }


    /**
     * showdoc
     *
     * @param ids 必选 List<Long> 页数
     * @catalog JhfbStu
     * @title 删除数据
     * @description 删除数据接口
     * @method post
     * @url http://localhost/user/sys-user/del
     * @remark 无
     * @number 7
     */
    @RequiresPermissions("JhfbStu:del")
    @RequestMapping("/del")
    @ResponseBody
    public BaseResponse deleteItems(@RequestParam("ids") List<String> ids) {
        boolean isOk = targetService.removeByIds(ids);
        if (isOk) {
            return BaseResponse.success("数据删除成功！");
        }
        return BaseResponse.error("数据删除失败");
    }

    // @RequiresPermissions("JhfbPro:del")
    @RequestMapping("/analyze")
    @ResponseBody
    public BaseResponse analyze(@RequestParam("proId") String proId) {
        List<JhfbStu> listStu = null;
        List<JhfbStu> tmpList = null;
        LinkedMap resMap = new LinkedMap();
        LinkedMap analyzeMap = new LinkedMap();
        try {
            //查询pro_id对应的学生信息，并且根据学生班级编号升序
            String paramData = "[{column: \"pro_id\",type: \"eq\", value: \"" + proId + "\"},{column: \"new_class\",type: \"orderByAsc\"}]";
            QueryWrapper<JhfbStu> queryWrapper = MybatisPlusQuery.parseWhereSql(paramData);
            listStu = targetService.list(queryWrapper);
            //用于统计各民族的人数，超过10个学生的，最后需要进行统计展示
            Map<String, Integer> nationTmpMap = new HashMap<>();
            //
            LinkedHashMap<String,Integer> resNationMap = new LinkedHashMap<>();
            for (JhfbStu tmp : listStu) {
                tmpList = new ArrayList<JhfbStu>();
                if (resMap.containsKey("班级" + tmp.getNewClass())) {
                    tmpList = (List<JhfbStu>) resMap.get("班级" + tmp.getNewClass());
                }
                tmpList.add(tmp);
                resMap.put("班级" + tmp.getNewClass(), tmpList);
                //统计
                if (nationTmpMap.containsKey(tmp.getNation())) {
                    nationTmpMap.put(tmp.getNation(), nationTmpMap.get(tmp.getNation()) + 1);
                } else {
                    nationTmpMap.put(tmp.getNation(), 1);
                }

            }
            //根据民族数据进行排序，统计分析时候，民族人数多的列前置时候需要用到
            List<Map.Entry<String,Integer>> list = new ArrayList<Map.Entry<String,Integer>>(nationTmpMap.entrySet());
            Collections.sort(list,new Comparator<Map.Entry<String,Integer>>() {
                //降序排序
                @Override
                public int compare(Map.Entry<String, Integer> o1,
                                   Map.Entry<String, Integer> o2) {
                    //先o1再o2即为降序
                    return o2.getValue().compareTo(o1.getValue());
                }
            });
            for (Map.Entry<String, Integer> entry : list) {
                resNationMap.put(entry.getKey(),entry.getValue());
            }

            for (Object key : resMap.keySet()) {
                List<JhfbStu> stu_tmp = (List<JhfbStu>) resMap.get(key);
                analyzeMap.put(key, resAve(stu_tmp, 1,resNationMap));
            }
            //误差值
            LinkedMap cpMap = new LinkedMap();
            for (Object key : resMap.keySet()) {
                LinkedMap obj = (LinkedMap) analyzeMap.get(key);
                for (Object keyOne : obj.keySet()) {
                    if (cpMap.containsKey(keyOne)) {
                        cpMap.put(keyOne, cpMap.get(keyOne) + "," + obj.get(keyOne));
                    } else {
                        cpMap.put(keyOne, obj.get(keyOne));
                    }
                }
            }
            analyzeMap.put("误差", cpRes(cpMap));
            //平均数
            analyzeMap.put("平均数", resAve(listStu, resMap.size(),resNationMap));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return BaseResponse.success(analyzeMap);
    }

    /**
     * 计算各班级各参数误差
     *
     * @param cpMap
     * @return
     */
    private LinkedMap cpRes(LinkedMap cpMap) {
        LinkedMap resMap = new LinkedMap();
        String[] data = null;
        BigDecimal cpData = new BigDecimal(0);
        for (Object keyOne : cpMap.keySet()) {
            if (StrUtil.isNotEmpty(cpMap.get(keyOne).toString())) {
                data = cpMap.get(keyOne).toString().split(",");
                Arrays.sort(data, new com());

                cpData = new BigDecimal(data[data.length - 1]).subtract(new BigDecimal(data[0]));
                resMap.put(keyOne, cpData);
            }
        }
        return resMap;
    }

    /**
     * 重写比较方法，主要用于计算字符串的数字
     *
     * @param <T>
     */
    class com<T> implements Comparator<T> {
        public int compare(T o1, T o2) {
            BigDecimal i = new BigDecimal(String.valueOf(o1));
            BigDecimal j = new BigDecimal(String.valueOf(o2));
            if (i.compareTo(j) == 1) {
                return 1;
            }
            if (i.compareTo(j) == -1) return -1;
            return 0;
        }
    }

    /**
     * 根据集合计算各项平均数
     *
     * @param listStu
     * @param size
     * @return
     */
    public LinkedMap resAve(List<JhfbStu> listStu, int size,Map<String,Integer> resNationMap) {
        BigDecimal all_score = new BigDecimal(0);//总分
        BigDecimal stu_num = new BigDecimal(0);//总分
        BigDecimal math_score = new BigDecimal(0);//数学总分
        BigDecimal english_score = new BigDecimal(0);//外语总分
        BigDecimal his_score = new BigDecimal(0);//道德与法制、历史总分
        BigDecimal language_score = new BigDecimal(0);//语文总分总分
        BigDecimal phy_score = new BigDecimal(0);//物理化学总分
        int m_num = 0;//男生人数
        int w_num = 0;//女生人数
        int hz_num = 0;//汉族人数
        int oth_num = 0;//其他族人数
        //存放民族的数量
        LinkedMap countMap = new LinkedMap();
        for (String key : resNationMap.keySet()){
            //遍历总得民族集合，将展示顺序确定
            //if(tmpNationMap.get(key)>10){
                countMap.put(key,0);
           // }
        }
        //最后放入其他民族
        //countMap.put("其他民族",0);
        LinkedMap aveMap = new LinkedMap();
        try {
            for (JhfbStu tmp : listStu) {
                all_score = all_score.add(new BigDecimal(tmp.getAllScore()));
                stu_num = stu_num.add(new BigDecimal(1));
                math_score = math_score.add(new BigDecimal(tmp.getMathScore()));
                english_score = english_score.add(new BigDecimal(tmp.getEnglishScore() == null ? "0" : tmp.getEnglishScore()));
                his_score = his_score.add(new BigDecimal(tmp.getHisScore() == null ? "0" : tmp.getHisScore()));
                language_score = language_score.add(new BigDecimal(tmp.getLanguageScore() == null ? "0" : tmp.getLanguageScore()));
                phy_score = phy_score.add(new BigDecimal(tmp.getPhyChemistryScore() == null ? "0" : tmp.getPhyChemistryScore()));
                if ("男".equals(tmp.getSex())) {
                    m_num++;
                } else {
                    w_num++;
                }
                //if(tmpNationMap.get(tmp.getNation())>10){
                    if(countMap.containsKey(tmp.getNation())){
                        countMap.put(tmp.getNation(),(Integer) countMap.get(tmp.getNation())+1);
                    }else{
                        countMap.put(tmp.getNation(),1);
                    }
                //}else{
                   // countMap.put("其他民族",(Integer)countMap.get("其他民族")+1);
                //}
            }
            aveMap.put("all_score", all_score.divide(new BigDecimal(listStu.size()), 2, BigDecimal.ROUND_HALF_UP).toString());
            aveMap.put("stu_num", stu_num.divide(new BigDecimal(size), 2, BigDecimal.ROUND_HALF_UP).toString());
            aveMap.put("math_score", math_score.divide(new BigDecimal(listStu.size()), 2, BigDecimal.ROUND_HALF_UP).toString());
            aveMap.put("language_score", language_score.divide(new BigDecimal(listStu.size()), 2, BigDecimal.ROUND_HALF_UP).toString());
            aveMap.put("english_score", english_score.divide(new BigDecimal(listStu.size()), 2, BigDecimal.ROUND_HALF_UP).toString());
            aveMap.put("his_score", his_score.divide(new BigDecimal(listStu.size()), 2, BigDecimal.ROUND_HALF_UP).toString());
            aveMap.put("phy_score", phy_score.divide(new BigDecimal(listStu.size()), 2, BigDecimal.ROUND_HALF_UP).toString());
            aveMap.put("m_num", new BigDecimal(m_num).divide(new BigDecimal(size), 2, BigDecimal.ROUND_HALF_UP).toString());
            aveMap.put("w_num", new BigDecimal(w_num).divide(new BigDecimal(size), 2, BigDecimal.ROUND_HALF_UP).toString());
           // aveMap.put("nation", new BigDecimal(hz_num).divide(new BigDecimal(size), 2, BigDecimal.ROUND_HALF_UP).toString());
           // aveMap.put("oth_num", new BigDecimal(oth_num).divide(new BigDecimal(size), 2, BigDecimal.ROUND_HALF_UP).toString());
            for(Object key : countMap.keySet()){
                aveMap.put(key,new BigDecimal((Integer) countMap.get(key)).divide(new BigDecimal(size), 2, BigDecimal.ROUND_HALF_UP).toString());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return aveMap;
    }

    @RequestMapping("/export")
    @ResponseBody
    public void export(HttpServletResponse response, @RequestParam("proId") String proId) {
        try {
            String paramData = "[{column: \"pro_id\",type: \"eq\", value: \"" + proId + "\"},{column: \"new_class\",type: \"orderByAsc\"}]";
            QueryWrapper<JhfbStu> queryWrapper = MybatisPlusQuery.parseWhereSql(paramData);
            String[] attrName = new String[]{"姓名", "性别", "新班级", "准考证号", "证件号", "民族", "报名地州", "毕业学校", "学籍号", "团员", "语文成绩", "物理化学成绩", "数学成绩", "道德与法制、历史成绩", "外语成绩", "总成绩", "体育是否合格（1:是；0否）"};
            String[] attr = new String[]{"stuName", "sex", "newClass", "ticketNumber", "cardNum", "nation", "repCity", "graduateSchool", "stuNumber", "leagueMembers", "languageScore", "phyChemistryScore", "mathScore", "hisScore", "englishScore", "allScore", "sportScore"};
            String objPath = "com.cn.psys.system.entity.JhfbStu";
            ExcelUtil.export(response, targetService.list(queryWrapper), attrName, attr, objPath,"学生分班信息");
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

